/*
 * Copyright (C) 2008 Johan Maasing johan at zoom.nu Licensed under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package nu.zoom.catonine.tail;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Adds methods to a tailer to handle a regular expression that is used to break
 * the logged character stream into 'log blocks'. The characters matching the
 * regular expression is included in the log block. The regular expression can
 * be defined as starting or ending, which means that the matching characters is
 * etiher included in the start of a log block or at the end.s
 * 
 * @author "Johan Maasing" &lt;johan@zoom.nu&gt;
 */
abstract class AbstractRegularExpressionLogBlockTailer extends
		AbstractThreadedTailer implements Tailer {

	private final Log log = LogFactory.getLog(getClass());
	private final Pattern DEFAULT_PATTERN = Pattern
			.compile("((\\n\\r?)|(\\r\\n?))");
	private Pattern pattern = DEFAULT_PATTERN;
	private AtomicBoolean blockMatcherStarting = new AtomicBoolean(false);

	public AbstractRegularExpressionLogBlockTailer() {
		super();
	}

	/**
	 * Set the regular expression that breaks log blocks.
	 * 
	 * @param pattern
	 *            The pattern, may not be null.
	 * @throws java.util.regex.PatternSyntaxEx
	 *             { this.pattern = DEFAULT_PATTERN; this.blockMatcherStarting =
	 *             false; ception
	 */
	@Override
	public synchronized void setLogBlockRegularExpression(Pattern pattern)
			throws PatternSyntaxException {
		if (log.isTraceEnabled()) {
			log.trace("Changed line ending reg.exp to: " + pattern.toString());
		}
		this.pattern = pattern;
	}

	/**
	 * Get the string representation of the block breaking regular expression.
	 * 
	 * @return
	 */
	@Override
	public synchronized String getLogBlockRegularExpression() {
		return pattern.toString();
	}

	/**
	 * Indicates if the characters that breaks a log block is in the start of
	 * the log block or in the end of the log block.
	 * 
	 * @return the blockMatcherStarting
	 */
	@Override
	public boolean isBlockMatcherStarting() {
		return blockMatcherStarting.get();
	}

	/**
	 * Tell if the characters that break a log block is in the start of the log
	 * block or in the end of the block.
	 * 
	 * @param blockMatcherStarting
	 *            the blockMatcherStarting to set
	 */
	@Override
	public void setBlockMatcherStarting(boolean blockMatcherStarting) {
		this.blockMatcherStarting.set(blockMatcherStarting);
	}

	protected synchronized Matcher createBlockMatcher() {
		return pattern.matcher("");
	}

	/**
	 * Reset the current pattern and block matcher starting to the default
	 * value.
	 */
	@Override
	public synchronized void setDefaultPattern() {
		this.pattern = DEFAULT_PATTERN;
		this.blockMatcherStarting.set(false);
	}
}
